﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.JavaScript;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Metadata.Entity.DataModel;

namespace T.FAS.Runtime.DataModel.Plugin
{
    public class CompositeDataObjectManager
    {
        public const string MetaDataID = DataModelConst.CDOMetaType;
        public const string MetaDataName = "复合数据对象";
        private readonly CompositeDataObjectLogic _compositeDataObjectLogic = new CompositeDataObjectLogic();
        /// <summary>
        /// 获取元数据内容
        /// </summary>
        /// <param name="metaDataId"></param>
        /// <returns></returns>
        public IMetaDataContent GetMetaDataContent(string metaDataId)
        {
            if (string.IsNullOrEmpty(metaDataId))
                throw new FasException(DataModelErrorCode.CDO.RetrieveError, $"{MetaDataName}id为空");
            var cdo = _compositeDataObjectLogic.GetCompositeDataObject(metaDataId);
            if (cdo == null)
            {
                throw new FasException(DataModelErrorCode.CDO.RetrieveError, $"{MetaDataName}:{metaDataId}不存在，请检查!");
            }

            cdo.MetaDataID = cdo.ID;
            cdo.MetaDataCode = cdo.Code;
            cdo.MetaDataName = cdo.Name;

            //Validate(cdo, CRUDType.RETRIEVE);
            return cdo;
        }

        /// <summary>
        /// 元数据保存
        /// </summary>
        /// <param name="metaData"></param>
        public void Save(IMetaDataContent metaData)
        {
            var cdo = metaData as CompositeDataObject;
            Validate(cdo, CRUDType.CREATE);
            FillCDOMetadataContent(metaData);
            _compositeDataObjectLogic.SaveCompositeDataObject(cdo);
        }

        /// <summary>
        /// 元数据删除
        /// </summary>
        /// <param name="metaData"></param>
        public void Delete(IMetaDataContent metaData)
        {
            Validate(metaData, CRUDType.DELETE);
            if (metaData == null || string.IsNullOrEmpty(metaData.MetaDataID))
                throw new FasException(DataModelErrorCode.NullValue, "metaData参数为空或IMetaDataContent.MetadataID为空");
            _compositeDataObjectLogic.DeleteCompositeDataObject(metaData.MetaDataID);
        }

        public void Import(List<IMetaDataContent> metaDatas)
        {
            var cdoList = new List<CompositeDataObject>();
            foreach (var metaData in metaDatas)
            {
                var cdo = metaData as CompositeDataObject;
                if (cdo == null)
                {
                    throw new FasException(DataModelErrorCode.ParamError, "元数据类型不是CDO, 实际类型:" + metaData.GetType().FullName);
                }

                cdoList.Add(cdo);
            }
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    _compositeDataObjectLogic.DeleteCompositeDataObjects(cdoList.Select(i => i.MetaDataID).ToList());

                    foreach (var cdo in cdoList)
                    {
                        _compositeDataObjectLogic.SaveCompositeDataObject(cdo);
                    }

                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.CDO.ImportError, "CDO元数据导入失败", e);
            }
        }
        public void Delete(List<string> IDs)
        {
            if (IDs == null)
                return;
            IDs = IDs.Where(id => id != null).ToList();
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    _compositeDataObjectLogic.DeleteCompositeDataObjects(IDs);
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.CDO.ImportError, $"{MetaDataName}元数据导入时删除失败", e);
            }
        }

        public ValidateResult Validate(IMetaDataContent metaData)
        {
            return new ValidateResult();
        }
        #region Private Funcs

        /// <summary>
        /// 填充CDO的系统字段内容
        /// </summary>
        /// <param name="metaData"></param>
        private void FillCDOMetadataContent(IMetaDataContent metaData)
        {
            CompositeDataObject CompositeDataObject = metaData as CompositeDataObject;
            if (CompositeDataObject == null)
            {
                throw new FasException(DataModelErrorCode.NullValue, $"{MetaDataName}Save方法参数有错误，请检查");
            }
            /***********低代码改动：Manager层只做系统默认字段的处理，CDO本身的逻辑放到Logic层处理*************/
            EntityTools.FillMainObjectFieldForAdd(CompositeDataObject, metaData);
        }

        /// <summary>
        /// 校验
        /// </summary>
        /// <param name="cdo"></param>
        /// <param name="type"></param>
        private void Validate(IMetaDataContent cdo, CRUDType type)
        {
            if (!ConfigTool.IsDebug(MetaDataID)) return;
            IMetaDataDesignValidator CompositeDataObjectValidator = new CompositeDataObjectValidator();
            if (type == CRUDType.RETRIEVE)
                CompositeDataObjectValidator.GetMetadata(cdo);
            else if (type == CRUDType.CREATE)
                CompositeDataObjectValidator.CreateMetadata(cdo);
            else if (type == CRUDType.DELETE)
                CompositeDataObjectValidator.DeleteMetadata(cdo);
            else if (type == CRUDType.UPDATE)
                CompositeDataObjectValidator.UpdateMetadata(cdo);
        }
        #endregion
    }
}
